import BoxUtil from "@/assets/js/utils/BoxUtil";
import Measure from '@/components/map/measure';
import SmQuery from '@/assets/js/utils/SmQuery';
import Binder from '@/utils/binder';
import Svg2Png from '@/utils/svg2png';
import '@/assets/mapbox/libs/draw/mapbox-gl-draw.css'
import MapBoxDraw from '@/assets/mapbox/libs/draw/mapbox-gl-draw.js'
import store from "@/store";
import popWin from "@/pages/xcgl/components/popWin";
import Vue from "vue";
import { add, remove, update } from '@/api/xcgl/ysbj'

export default class MapService {

  /**
   *  构造函数
   * @param mapBox HgcMapBoxUtil
   */
  constructor(mapBox,name) {
    this.hgcMapBoxUtil = mapBox; //地图操作基础类
    this.isMapInitComplete = false; //地图style初始化是否完成
    this.baseMapLayers = []; //当前显示的底图数组
    this.topCanvasLayers = []; //顶部不动的图层（标绘图层）
    this.getMap().on('style.load', this._mapStyleLoadComplete.bind(this)); //地图初始化
    this.mapDataEvent = {}; //地图数据加载事件
    this._m = new Measure(mapBox);
    this.binder = new Binder();
    this._svg = new Svg2Png();
    this.tempMarker = new mapboxgl.Marker();
    this._drawControl = undefined;
    this.drawControlStyles = [
     
    ];
    this.selectSymbol = undefined;
    this.drawControlCreate = this.drawControlCreate.bind(this);
    this.drawControlUpdate = this.drawControlUpdate.bind(this);
    this.drawControlDelete = this.drawControlDelete.bind(this);
    this.drawControlClick = this.drawControlClick.bind(this);
    this._drawControlModeChange = this._drawControlModeChange.bind(this);
    this.bindDrawControlEvent();
    this._remoteImages = [];
    this.popVue = new Vue({ render: h => h(popWin) });
    this.pop = new mapboxgl.Popup({
      closeOnClick: false, closeButton: true
    }).setDOMContent(this.popVue.$mount().$el);
    this.name = name;
  }



  /**
   * 获取PopWin实例
   */
  getPop() {
    return this.pop;
  }
  /**
   * 获取PopWin组件
   */
  openPop(fc, attribute, lnglat) {
    this.popVue.$children[0].setTemplate(fc, attribute);
    this.pop.setLngLat(lnglat).addTo(this.getMap());
  }

  /**
   * 绑定事件
   * @param event
   * @param fn
   */
  on(event, fn) {
    //console.log(this.name,'on',event,fn.name)
    if (typeof fn !== 'function') {
      console.error('第二个参数不是方法');
      return;
    }

    if (this.mapDataEvent[event] && Array.isArray(this.mapDataEvent[event])) {
      this.mapDataEvent[event].push(fn);
    } else {
      this.mapDataEvent[event] = [fn];
    } 
  }

  /**
   * 解绑事件
   * @param event
   * @param fn
   */
  off(event, fn) {
    //console.log(this.name,'off',event,fn.name)
    if (typeof fn !== 'function') {
      console.error('第二个参数不是方法');
      return;
    }
    if (this.mapDataEvent[event] && Array.isArray(this.mapDataEvent[event])) {
      const index = this.mapDataEvent[event].indexOf(fn);
      if (index != -1) {
        this.mapDataEvent[event].splice(index, 1);
      }
    } else {
      this.mapDataEvent[event] = [];
    }
  }

  /**
   * 添加Marker
   * @param {*} latlng 
   */
  addMarker(latlng) {
    this.tempMarker.remove();
    this.tempMarker.setLngLat(latlng).addTo(this.getMap());
  }
  /**
   * 删除Marker
   */
  removeMarker() {
    this.tempMarker.remove();
  }

  /**
   * 绑定标绘控件事件
   */
  bindDrawControlEvent() {
    this.getMap().on('draw.create', this.drawControlCreate)
    this.getMap().on('draw.update', this.drawControlUpdate)
    this.getMap().on('draw.delete', this.drawControlDelete)
    this.getMap().on('draw.modechange', this._drawControlModeChange);
    this.getMap().on('click', this.drawControlClick)
  }

  /**
  * 绘制添加
  * @param e
  */
  drawControlCreate(e) {

    const uid = this.selectSymbol ? this.selectSymbol._id : undefined;
    this._drawControl.setFeatureProperty(e.features[0].id, 'uid', uid);
    const param = e.features[0];
    param.uid = store.getters.id;
    param.properties = { uid: uid }
    param.taskId = store.state.xcgl.selectTask._id;
    param.dept = store.getters.dept;
    param.status = 0;
    add(param).then(res => {
      this._triggerMouseEvent('map.create', e, this._drawControl);
    })

  }

  /**
   * 绘制更新
   * @param e
   */
  drawControlUpdate(e) {
    const param = e.features[0];
    update(param).then(res => {
      this._triggerMouseEvent('map.update', e, this._drawControl);
    })

  }

  /**
   * 绘制删除
   * @param e
   */
  drawControlDelete(e) {
    const ids = e.features.map(o => o.id);
    remove({ ids: ids }).then(res => {
      this._triggerMouseEvent('map.delete', e, this._drawControl);
    })
  }

  /**
     * 触发
     * @param e
     * @private
     */
  _fireDrawControlDelete(e) {
    const ids = e.features.map(o => o.id);
    this._drawControl.delete(ids);
    this.drawControlDelete(e);
  }

  /**
   * 绘制点击
   * @param e
   */
  drawControlClick(e) {
    e.features = this._drawControl ? this._drawControl.getSelected().features : []
    this._triggerMouseEvent('click', e)
  }

  /**
   * 绘制改变模式
   * @param e
   * @private
   */
  _drawControlModeChange(e) {
    this._triggerMouseEvent('map.modechange', e);
  }

  /**
   * 地图Style加载完成事件
   * @private
   */
  _mapStyleLoadComplete() {
    this.isMapInitComplete = true;
    this._triggerMouseEvent('map.init', this.getMap());
    //this._addHighLightLayer();
    this._addQXJLayer();


  }

  //添加高亮(默认一张)
  _addHighLightLayer() {
    this.addSource('all-map-highlight-layer-source');
    this.hgcMapBoxUtil.addHightLightLayers('all-map-highlight-layer-source-point', 'all-map-highlight-layer-source', 'Point');
    this.hgcMapBoxUtil.addHightLightLayers('all-map-highlight-layer-source-linestring', 'all-map-highlight-layer-source', 'LineString');
    this.hgcMapBoxUtil.addHightLightLayers('all-map-highlight-layer-source-polygon', 'all-map-highlight-layer-source', 'Polygon');
  }

  /**
   * 添加区县界图层
   */
  _addQXJLayer() {

  }

  /**
   * 鼠标事件触发器
   * @param evt
   * @private
   */
  _triggerMouseEvent(evt, e, id) {
    let ev = this.mapDataEvent[evt];
    let size = ev ? ev.length : 0;
    for (let i = 0; i < size; i++) {
      //console.log(this.name+ "-----",ev[i].name)
      ev[i].apply(this, [e, id]);
    }
  }

  /**
   * 获取地图
   * @returns {*}
   */
  getMap() {
    return this.hgcMapBoxUtil.getMap();
  }

  /**
   * 获取测量工具
   * @returns {Measure}
   */
  getMeasureTool() {
    return this._m;
  }

  /**
   * 地图操作类
   * @returns {*}
   */
  getHgcMapBoxUtil() {
    return this.hgcMapBoxUtil;
  }

  /**
   * 解析图层url
   * @param url
   * @private
   */
  _parseLayerUrl(url) {
    if (url) {
      this._parseLayerUrlParam(url);
      const urlArray = url.split('?');
      const realUrl = url.replace(urlArray[urlArray.length - 1], '');
      return realUrl.substring(0, realUrl.length - 1);
    }
    return url
  }

  /**
   * 解析图层查询数据
   * @param url
   * @returns {*}
   * @private
   */
  _parseLayerQueryUrl(url) {
    const real = this._parseLayerUrl(url);
    if (real.indexOf('/tileFeature') === -1) {
      return real;
    } else {
      return real.substring(0, real.indexOf('/tileFeature'));
    }
  }

  /**
   * 解析图层url参数
   * @param url
   * @private
   */
  _parseLayerUrlParam(url) {
    if (url) {
      const urlArray = url.split('?');
      try {
        var obj = JSON.parse(
          '{"' +
          decodeURIComponent(urlArray[urlArray.length - 1])
            .replace(/"/g, '\\"')
            .replace(/&/g, '","')
            .replace(/=/g, '":"') +
          '"}'
        )
      } catch (e) {
        console.warn("图层URL参数配置不正确，不能正常解析的JSON");
        return {};
      }
      return obj;
    }

  }

  /**
   *  添加图层
   * @param type
   * @param id    layerId的真实身份是sourceId
   * @param url
   * @param minZoom
   * @param maxZoom
   * @param beforeID
   * @returns {*}
   */
  addLayer(layer, beforeID) {
    const realUrl = this._parseLayerUrl(layer.url);
    const param = this._parseLayerUrlParam(layer.url); //layerType,searchLayer
    let promise;

    switch (param.layerType.trim()) {
      case "layer_sm_vec": //超图发布的矢量瓦片服务
        promise = this.hgcMapBoxUtil.addVectorTileLayerMD(realUrl, beforeID, layer.minZoom, layer.maxZoom);
        break;
      case "layer_sm_map": //栅格瓦片服务
        promise = this.hgcMapBoxUtil.addGridTileLayer(layer.param ? (layer.param.layers ? layer.param.layers[0].id : undefined) : undefined, realUrl, layer.minZoom, layer.maxZoom, beforeID);
        break;
      case "layer_sm_25d": //2.5D服务
        promise = this.hgcMapBoxUtil.addFillExtrusionLayer(layer.param ? layer.param.id : undefined, realUrl, layer.minZoom, layer.maxZoom, beforeID); //TODO  undefined 是sourcelayer
        break;
      case 'layer_tdt_map': //天地图栅格瓦片服务
        promise = this.hgcMapBoxUtil.addTdtGridTileLayer(layer.param ? (layer.param.layers ? layer.param.layers[0].id : undefined) : undefined, realUrl, layer.minZoom, layer.maxZoom, beforeID);
        break;
      case 'layer_sm_es': //EChart服务
        promise = this.hgcMapBoxUtil.addEchartsLayer(layer.url);
        break;
      default:

        break;
    }
    return promise;
  }


  /**
   * 获取专题最下面的图层
   * @returns {undefined}
   */
  getSubjectLayersBottomLayerId() {
    var layers = this.getMap().getStyle().layers;
    if (layers && Array.isArray(layers) && layers.length > 0) {
      return layers.length > 0 ? layers[0].id : undefined;
    }
    return undefined;
  }

  /**
   * 设置图层开关
   *
   * 先对图层添加和删除，再对高亮图层的添加和删除
   * 再绑定图层的属性查询事件
   */
  setLayerVisible(isVisible, layer, beforeId) {
   
  }

  /**
   * 注册鼠标事件
   * @param id
   * @private
   */
  _addMouseEventListener(id, layer) {
    this.getMap().on('mouseenter', id, this.binder.bind(this._mouseEnterEvent, this, [id], id + '_mouseEnterEvent'));
    this.getMap().on('mouseleave', id, this.binder.bind(this._mouseLeaveEvent, this, [id], id + '_mouseLeaveEvent'));
    this.getMap().on('click', id, this.binder.bind(this._mouseClickEvent, this, [id, layer], id + '_mouseClickEvent'));
  }


  /**
   * 取消鼠标事件
   * @param id
   * @private
   */
  _removeEventListener(id) {
    this.getMap().off('mouseenter', id, this.binder.getBindFunction(id + '_mouseEnterEvent'));
    this.getMap().off('mouseleave', id, this.binder.getBindFunction(id + '_mouseLeaveEvent'));
    this.getMap().off('click', id, this.binder.getBindFunction(id + '_mouseClickEvent'));
  }

  /**
   * 鼠标停留在要素上方
   * @param e
   * @private
   */
  _mouseEnterEvent(id, e) {
    this.getMap().getCanvas().style.cursor = 'Pointer';
    this._triggerMouseEvent('map.enter', e, id);
  }

  /**
   * 鼠标离开要素上方
   * @param e
   * @private
   */
  _mouseLeaveEvent(e) {
    this.getMap().getCanvas().style.cursor = '';
  }

  //  鼠标点击事件
  _mouseClickEvent(id, e) {
    this._triggerMouseEvent(id[1].type === 'base' ? 'map.base.click' : 'map.click', e, id); //广播出去
    //this.hgcMapBoxUtil.setHighLightFilter2(id[0], e.features ? e.features[0].id : undefined);
    this.setData('all-map-highlight-layer-source', { type: "FeatureCollection", features: e.features });
  }


  /**
   * 设置图层透明度
   * @param value
   * @param sourceId 数据源ID
   */
  setOpacityValue(value, layer) {
    if (layer.param && layer.param.layers) {
      this.hgcMapBoxUtil.setLayerOpacity(layer.param.layers[0].source, value);
    }
  }

  /**
   * 移除瓦片
   * @param soureId 数据源ID
   */
  removeLayer(sourceId) {
    this.hgcMapBoxUtil.removeTileLayer(sourceId);
  }

  /**
   * 切换底图
   * @param layerGroup
   */
  async addBaseLayer(layerGroup) {
    if (!Array.isArray(layerGroup)) {
      throw ('layerGroup 不是个数组，检查数据！');
    }

    //移除
    this.baseMapLayers.forEach(layer => {
      this.removeLayer(layer.layers[0].source);
      this._removeEventListener(layer.layers[0].id);
    });
    this.baseMapLayers = [];
    //这里剩下专题图层
    var bottom = this.getSubjectLayersBottomLayerId();
    if (!bottom && this.topCanvasLayers.length > 0) {
      bottom = this.topCanvasLayers[0];
    }
    //排序再添加
    layerGroup.sort((p, n) => parseInt(n.index) - parseInt(p.index));

    //添加图层到地图
    for (let i = 0; i < layerGroup.length; i++) {
      const layer = layerGroup[i];
      const res = await this.addLayer(layer, bottom);
      this.baseMapLayers.push({ layers: res });
      const param = this._parseLayerUrlParam(layer.url)
      //地图含有可查询的矢量瓦片数据
      for (let i = 0; i < res.length; i++) {
        const l = res[i];
        if (param.search && l['source-layer'] && l.type) {
          this._addMouseEventListener(l.id, layer);
          //this.hgcMapBoxUtil.addHighLightLayer(l.source, l.id, l['source-layer'], l.type);
        }
      }

    }

  }

  /**
   * 通过图层边界设置地图边界
   * @param layer
   */
  async setMapBoundsByLayerBounds(layer) {
   

  }


  /**
   * 加载系统符号库的点图片
   * @param s
   * @private
   */
  _loadPointImage(s) {
    const image = this._svg.getCanvasImageData(s.flag, {
      strokeStyle: s.strokeStyle,
      fillStyle: s.fillStyle,
      lineWidth: s.lineWidth
    });
    this.hgcMapBoxUtil.addPng(s._id, image);
  }


  /**
   * 属性查询
   * @param layer
   * @param startIndex
   * @param size
   * @returns {Promise<never> | Promise<any>}
   */
  queryLayerAttribute(layer, startIndex, size, sql) {
  
  }

  /**
   * 定位Geometry
   * @param geometry
   */
  flyTo(geometry, zoom) {
    switch (geometry.type) {
      case 'Point':
          this.getMap().flyTo({ center: geometry.coordinates,zoom: zoom || 13})
        break
      case 'LineString':
        var bounds = BoxUtil.getCoordinatesBounds(geometry.coordinates)
        this.getMap().fitBounds(bounds, { padding: 50 })
        break
      case 'Polygon': // 闭合
        var bounds = BoxUtil.getCoordinatesBounds(geometry.coordinates[0])
        this.getMap().fitBounds(bounds, { padding: 50 })
        break
    }
  }

  /**
   * 设置高亮
   * @param layerId
   * @param smId
   */
  setHightLihgtFilter(layerId, smId) {
    this.hgcMapBoxUtil.setHighLightFilter(layerId, smId)
  }

  /**
   * 清除高亮
   * @param layerId
   */
  clearHightLightFilter(layerId) {
    this.hgcMapBoxUtil.clearHighLightFilter(layerId);
  }


  /**
   * 给Map加载符号库
   * @param symbols
   */
  addloadSymbols(symbols) {
    if (!Array.isArray(symbols)) {
      return;
    }
    symbols.forEach(symbol => {
      this.hgcMapBoxUtil.addImage(symbol.symbolName, symbol.symbolPath);
    });
  }


  /**
   * 创建DrawControl
   * @param symbols
   * @returns {MapBoxDraw|*}
   */
  createDrawControl(symbols) {
 
  }


  /**
   * 更改模式
   * @param mode
   */
  setChangeMode(mode, selectId) {
    if (this._drawControl) {
      this._drawControl.changeMode(mode, selectId);
    }

  }


  /**
   * 设置符号库
   * @param symbol
   */
  setSelectSymbol(symbol) {
    this.selectSymbol = symbol;
    console.log(this.name,this.mapDataEvent)
  }

  /**
   * 获取drawControl
   * @returns {*|MapBoxDraw}
   */
  getDrawControl() {
    return this._drawControl;
  }

  /**
   * 图层统计
   * @param layer
   * @param startIndex
   * @param size
   * @returns {Promise<never> | Promise<any>}
   */
  queryLayerStatics(url, name, field) {

  }

  addSource(sourceId) {
   
  }

  addGeoJsonLayer(id, json) {

  }

  removeGeoJsonLayer(sourceId) {
   
  }


  /**
  * 清除遥感数据
  */
  clearRemoteImageLayers() {

  }

  /**
  * 添加遥感影像图层
  * @param layers
  */
  leftRemoteImageLayers(layers, beforeID) {
    //先清除图层
    //再添加图层
    this.clearRemoteImageLayers();
    this._remoteImages = [];
    for (let i = 0; i < layers.length; i++) {
      let layer = layers[i];
      //基础地图之上专题图层之下
      let bottomOfTopLayerId = beforeID ? beforeID : (this.drawControlStyles && this.drawControlStyles.length > 0 ? this.drawControlStyles[0].id + ".cold" : undefined);
      const isExist = this.hgcMapBoxUtil.isLayerExist(bottomOfTopLayerId)
      this.addLayer(layer, (isExist ? bottomOfTopLayerId : undefined)).then(res => {
        layer.param = { layers: res };
      });
      this._remoteImages.push(layer);
    }

  }


  rightRemoteImageLayers(layers, beforeID) {
    this.leftRemoteImageLayers(layers, beforeID)
  }
  /**
 * 设置数据
 * @param {数据源名称} dsName 
 * @param {*} fc 
 */
  setData(dsName, fc) {
    if (!this.getMap().getSource(dsName)) {
      return;
    }
    this.getMap().getSource(dsName).setData(fc);
  }
  /**
   * 获取标绘内容
   */
  getDrawControlFC() {
    if (this._drawControl) {
      return this._drawControl.getAll();
    }
    return undefined;

  }
  /**
   * 设置标绘内容
   * @param {*} fc 
   */
  setDrawControlFC(fc) {
    if (this._drawControl) {
      this._drawControl.set(fc);
    }
  }
  /**
   *  设置边界
   * @param {*} bounds 
   * @param {*} padding 
   */
  setBounds(bounds, padding) {
    this.getMap().fitBounds(bounds, { padding: padding });
  }

  setDrawControlHighLight(type, ids) {
    this._drawControl.changeMode(type, ids);
  }


}
